package com.tbit.uqbike.client.remote.zfb;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.tbit.common.utils.SpringContextUtils;
import com.tbit.uqbike.client.config.RefundSwitchConfig;
import com.tbit.uqbike.client.constant.RabbitMQData;
import com.tbit.uqbike.client.constant.RedisConstant;
import com.tbit.uqbike.client.constant.RefundConstant;
import com.tbit.uqbike.client.dao.log.RefundOrderDao;
import com.tbit.uqbike.client.pojo.RefundOrder;
import com.tbit.uqbike.client.pojo.WeixinDepositLog;
import com.tbit.uqbike.client.pojo.ZfbPayConfig;
import com.tbit.uqbike.client.pojo.newEntity.CallbackDataVo;
import com.tbit.uqbike.client.pojo.newEntity.PayCallbackData;
import com.tbit.uqbike.client.remote.zfb.config.AlipayConfig;
import com.tbit.uqbike.client.service.MQProducer;
import com.tbit.uqbike.client.service.RedisService;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.LogUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * 支付宝退款
 *
 * @author Leon
 * 2017年11月9日 上午11:45:44
 */
@Slf4j
public class ZFBReturn {
    /**
     * 退款接口
     *
     * @param zfbPayConfig
     * @param weixinDepositLog
     * @return
     */
    @SuppressWarnings("deprecation")
    public static Boolean returnMoney(ZfbPayConfig zfbPayConfig, WeixinDepositLog weixinDepositLog) {
        try {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", zfbPayConfig.getPartner(), zfbPayConfig.getPrivate_key(), "json", AlipayConfig.input_charset, zfbPayConfig.getAli_public_key(), "RSA2");
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.setBizContent("{" + "\"out_trade_no\":\"" + weixinDepositLog.getOut_trade_no() + "\"," + "\"trade_no\":\"" + weixinDepositLog.getTransaction_id() + "\"," + "\"refund_amount\":" + weixinDepositLog.getDepositMoney() / 100 + "," + "\"refund_reason\":\"正常退款\"," + "\"out_request_no\":\"" + weixinDepositLog.getOut_refund_no() + "\","
                    + "\"operator_id\":\"OP001\"," + "\"store_id\":\"NJ_S_001\"," + "\"terminal_id\":\"NJ_T_001\"" + "  }");
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            LogUtil.info(response.getBody());
            if (response.isSuccess()) {
                return true;
            } else {
                LogUtil.warn(response.getErrorCode() + "," + response.getMsg());
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return false;
    }

    /**
     * 退款
     *
     * @param zfbPayConfig
     * @param out_trade_no
     * @param refund_no
     * @param money
     * @return
     */
    public static Boolean returnMoneyNew(ZfbPayConfig zfbPayConfig, String out_trade_no, String refund_no, double money) {
        // 退款，在调用起始处已经加了分布式锁
        boolean result = false;
        try {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", zfbPayConfig.getPartner(), zfbPayConfig.getPrivate_key(), "json", AlipayConfig.input_charset, zfbPayConfig.getAli_public_key(), "RSA2");
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.setBizContent("{" + "\"out_trade_no\":\""+out_trade_no+"\"," + "\"refund_amount\":"+money/100+"," + "\"refund_reason\":\"正常退款\"," + "\"out_request_no\":\""+refund_no+"\","
                    + "\"operator_id\":\"OP001\"," + "\"store_id\":\"NJ_S_001\"," + "\"terminal_id\":\"NJ_T_001\"" + "  }");
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            log.info("支付宝调用结果{}",response.getBody());
            if (response.isSuccess()){
                result = true;
            } else if (Objects.equals(response.getSubCode(),"aop.ACQ.SYSTEM_ERROR") || Objects.equals(response.getCode(),"20000")) {
                // 支付宝系统错误 ， 相同参数重试 ， 重试上限为两次
                for (int i = 0; i < 2; i++) {
                    response = alipayClient.execute(request);
                    log.warn("支付宝第{}次重试，重试结果{}",i+1,response.getBody());
                    if (response.isSuccess()){
                        result = true;
                        break;
                    }
                }
            }
            if (!response.isSuccess()){
                log.warn("支付宝退款失败，错误码{}，错误信息{}",response.getErrorCode(),response.getMsg());
            }

            RefundSwitchConfig refundSwitchConfig = SpringContextUtils.getBean("refundSwitchConfig");
            String refundModel = refundSwitchConfig.getRefundModel();
            if (Objects.equals(refundModel,RefundSwitchConfig.REFUND_NEW)){
                // 异步等待500ms   refundorder 记录完全
                AlipayTradeRefundResponse finalResponse = response;
                new Thread(() -> {
                    try {
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    RefundOrderDao refundOrderDao = SpringContextUtils.getBean("refundOrderDao");
//                log.info("工具类静态方法中通过SpringContextUtils获取refundOrderDao={}", refundOrderDao);
                    MQProducer mqProducer = SpringContextUtils.getBean("mQProducerService");
//                log.info("工具类静态方法中通过SpringContextUtils获取mqProducer={}", mqProducer);
                    RefundOrder refundOrder = null;
                    RedisService redisService = SpringContextUtils.getBean("redisService");
                    if (!redisService.setNx(RedisConstant.REFUND_LOCK + "callback" + refund_no, RedisConstant.REFUND_LOCK, 60)) {
                        log.warn("获取分布式锁失败{}", refund_no);
                    }
                    // 需要确保当同步返回结果为success时，一定返回true
                    try{
                        refundOrder = refundOrderDao.getByRefundNO(refund_no);
                        if (finalResponse.isSuccess()) {
                            if (Objects.isNull(refundOrder)) {
                                log.error("回调时获取退款订单表为空，排查执行退款时的退款订单表插入动作问题，退款单号={}", refund_no);
                            }
                            // 进一步判断是否同步退款成功，并进行退款订单表记录和MQ消息发送
                            if ("Y".equalsIgnoreCase(finalResponse.getFundChange())) {
                                // 记录退款订单表状态为退款成功，记录MQ推送消息
                                // 记录退款订单信息
                                if (Objects.nonNull(refundOrder) && !refundOrder.getMsgSuccess()) {
                                    // 发送MQ消息
                                    PayCallbackData msgData = new PayCallbackData();
                                    CallbackDataVo callbackDataVo = new CallbackDataVo();
                                    callbackDataVo.setPaymentId(finalResponse.getTradeNo());  //第三方支付id 是啥? 支付宝交易号
                                    callbackDataVo.setType(2);  // 类型 1 支付 ， 2 退款
                                    callbackDataVo.setStatus("SUCCESS");
                                    callbackDataVo.setOrderNo(refund_no); // 单号（订单号 退单号）
//                            callbackDataVo.setTotalRefundMoney(String.valueOf(totalRefundMoney));
                                    callbackDataVo.setRefundMoney(String.valueOf(money)); // 退款金额
                                    callbackDataVo.setConfirmTime(DateTimeUtil.getNowTime());   // 支付时间  退款时间
                                    callbackDataVo.setTransactionId(out_trade_no);  // 平台交易号
                                    callbackDataVo.setFee_amt(finalResponse.getRefundFee());
                                    msgData.setData(callbackDataVo);
                                    // 记录MQ消息内容
//                            refundOrder.setMessageId(msgId);
                                    refundOrder.setMessageContent(JSON.toJSONString(msgData));
                                    refundOrder.setRouteKey(RabbitMQData.orderkey);
                                    refundOrder.setExchange(RabbitMQData.orderexchange);
                                    // 设置消息消费状态为未消费
                                    refundOrder.setMsgSuccess(false);

                                    // 修改订单退款状态为成功
                                    refundOrder.setRefundStatus(RefundConstant.REFUND_SUCCESS);
                                    // 跟新退款订单状态
                                    refundOrderDao.updateCallBackInfo(refundOrder);
                                    log.info("发送MQ消息{}", JSON.toJSONString(msgData));
                                    mqProducer.sendToRide(RabbitMQData.orderexchange, RabbitMQData.orderkey, JSON.toJSONString(msgData));
                                }
                            } else {
                                if (Objects.nonNull(refundOrder)) {
                                    // 记录退款订单表状态为退款失败
                                    refundOrder.setRefundStatus(RefundConstant.REFUND_FAIL);
                                    refundOrder.setErrorMsg(finalResponse.getMsg());
                                    refundOrderDao.updateCallBackInfo(refundOrder);
                                }
                            }
                        } else {
                            if (Objects.nonNull(refundOrder)) {
                                // 记录退款订单表状态为退款失败
                                refundOrder.setRefundStatus(RefundConstant.REFUND_FAIL);
                                refundOrder.setErrorMsg(finalResponse.getMsg());
                                refundOrderDao.updateCallBackInfo(refundOrder);
                            }
                            log.warn(finalResponse.getErrorCode() + "," + finalResponse.getMsg());
                        }
                    } finally {
                        redisService.del(RedisConstant.REFUND_LOCK + refund_no);
                    }
                }).start();
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return result;
    }
    public static void main(String[] args) {
		/*ZfbPayConfig zfbPayConfig = new ZfbPayConfig();
		zfbPayConfig.setPartner("2021002103671593");
		zfbPayConfig.setPrivate_key("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBW7C9Vai4Xqkn/h9bJNaLifzBA6GUU8qEMoz8/+QoQmft3Sh4rTjc4huXv8ApIY4MZFnpiv1yqAKEjfeS3wfWfrFpWcyK7T3jtw5yVp0NHvDPqyhM2vsr15yYPR2M4dFIbu3BXY27ph3eEqL3g7IhzYH7D0ub/7u7BFZNboV9zM5BVsK4hbWL/N+Pv2XRbyzXS+G6la/xrp+NCH3UsDJkONwjbzxU/Lbzy6oQhbllPt9XpOsupiEAmoaQHZVwX0BZPbZ0OTwPJifXAZC6ybPWUNGAgD/IdheQSx1WP9ZmgkREa3Q/WxxaUta/AHXQGtB7Ayytj/ISmrUu15irCyC7AgMBAAECggEAW8jYRe9SkMcx1Rud2gjwZgAZpEZUTq+JgXVwzk8u71X28jK69a1LLIcOtwSqb0TMyoQlu+0P2lvVtYIaCU9Q+2PXs/2wgV7GTB3mFUDZnKa4jVFPfgDeuQP6q5apsf3EhlWXQ12DJINArAKjOWZrbUqpEJ+QsXaqGI+CQNzLwS8fMlO6xdxTyl5sXoSWHOPsEg1XGRp4KIAVysLfzrCuBfT/kY1B6HbjS9MT37S7ItkNssH89PrpZJdnyHp9UiDlsCkl/RbGXeQgBkoegRmm1w1AYlGOtpxxO4pPOjslZzwVkykj4RA8372GvIIoPA/HUCrNjB3+yxbxXspKFjNhsQKBgQC9cA8WdM2EbEVe8tvnVbZdT5Idm1Glas8y20ULcBpfdPsm8x87QgnrFcgdLQcid776O3++YZ73kyGlF3ULXCFIWCFwtUmTpqO6p4q7b1NXMmxDpzbv33iJiFKa2XNDd5sPLBqkEj96VOa1TmP0lFdqQWJEMri+wjMUJ5QZR1qeOQKBgQCuz3gaJAZyD2Gr3jQJvHVC6NYNIWM/vad76tJhJbfQpA49EQQeAAtjwN3yEiuVB95lLJ5hXYI5bFKclEQGhaNfAeShRmOKgADSetjOTrFtmRiyj2lhTklNcYwvHOamHIcuI/dkHMSHb7ihCmKCIpZw+ihk41rexPVECPd3FbR2kwKBgCmPbh/1HCmTP1znVwtXqJysGlhYfP8XgcGcjXdG7uJGXdtbt1xezqI+sxqDiG8taj6n0wzHigKyyszXapxFaB/hBeUeQLgd9Qm8PBmHAPe+XjYxd0IE+wLhX44NatZAZUpc2LNqNXb3LW5VdmRwLwVmttJTdmiTXnVrgXhSSTUxAoGAeJaj+hxp2drkfKP+78xyc6Kcrlge2ASjeacGU3+qaqIRNGz9kxhiwwBz2p5QNDFGaDK8Wtwfji88Wckpl/ouNcbfiaU923frmUanMsI0QS+ASwUFI9vWUzcGBiYAsgwx8FFdQlFZ/TfDfEvmonDrqKnYnaf8snnZ24H3+80cPUMCgYAjGhqlD0yWicEEiBDgaXTco2BKgg2oBrToyHt8ISpNWaV1cLzZKYofHBN++asJyZQqhWGwl0BDU3CVRfyTg9Uq5c23zdPvPtifJBS/JEkBZ8N8OqSMW2PzBfr9V9ItXAZYecI8phTcU5v+DlqFHMNXeaCH0CWSJV62dBcC31yHXQ==");
		zfbPayConfig.setAli_public_key("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlcQMS5IbDd1XGqBB4xYHU7D9DPc3WrTY3WYHlnq3+2JCjLpsurtveE/DY6R2ntO4S7U+er0GksraNeyZT0FViwTRxKzBrVVooaqV8qI0wWRd1m8HCvCClyxndWg06OGRy4LvJrsEmAPWJVs6ELlAyYSkWpXP3HqV3cFbk3sdy9reeyIrlFEUUAz8Mn7u4k94j/VYMAz2hETDe9A2+S+UKPjANqvI8wl/aO5vBkxcN0JfQUP8WIUXg/Ko1Rm4B1ygSxzjvYkUk/WF5FnZnL2IgvLfQw5oKJ56q3dFLGpAm9/DD8q3gbcb6vmKuX4FEkQYom9Zjcx/GvVchvIk4aQqFQIDAQAB");
		String refundNO= WeixinPayUtil.getReturnNonceStr();
		System.out.println(returnMoneyNew(zfbPayConfig,"GXBIKEDM20210910130657451102",refundNO,390));*/
    }

}
